02. External Data

We're going to use a database to interact with our Todos application. We're simulating the database to keep that aspect of the project less complex. This is the HTML script tag you need to add the database to your application which we'll use in the following video:

<script src="https://tylermcginnis.com/goals-todos-api/index.js"></script>

Using A Remote API

Task Description:

Working with a new API can be a bit tricky. Make sure to check off each of the following.

Task List:

Task Feedback:

Great work, keep going!

Which Method?

QUESTION:

Take a look at the API. Which method will get all Goals?

SOLUTION:

These answers need to be solved by yourself, I believe you can do it

How long will it run?

From the API, how long will the saveTodo method run before stopping itself?

SOLUTION: 0.3 seconds

🔨Task

Add the following behavior to the project:

  • When the app loads, console.log all of the todos and all of the goals that reside in our fake database.

Solution Code

Once you've tried your hand at tackling the task above, hover your mouse here for a possible solution.
class App extends React.Component {
      componentDidMount () {
        const { store } = this.props

        Promise.all([
          API.fetchTodos(),
          API.fetchGoals()
        ]).then(([ todos, goals ]) => {
          console.log('Todos', todos)
          console.log('Goals', goals)
        })
        ...
}

Promise-Based API

The methods in the provided API are all Promise-based. Let's take a look at the .fetchTodos() method:

API.fetchTodos = function () {
  return new Promise((res, rej) => {
    setTimeout(function () {
      res(todos);
    }, 2000);
  });
};

See how we're creating and returning a new Promise() object?

In the task above, you could've just fetched all of our todos and then all of our Goals, but that's serial and is just making the user wait an unnecessarily long amount of time. Since the API is Promise-based, we can use Promise.all() to wait until all Promises have resolved before displaying the content to the user.

Promises are asynchronous, and this lesson is all about working with asynchronous data and asynchronous requests. If you're feeling a little unsure about Promises, check out the Promise documentation on MDN or check out our JavaScript Promises course.

Handling Initial Data

Flash Of No Data

Implementing a Loading Indicator

QUESTION:

At this point, when we refresh our app, only the UI seems to load. There is a noticeable delay before any of the data (i.e., todos and goals) actually appears on the screen. To ensure a smooth experience for users, it would be great if we can have a loading indicator on the screen as content is being fetched.

How would you implement this feature? Should this be tracked in the state? Do we need to make a new component? What about our reducers -- should they require any new logic? Please write your thoughts below.

ANSWER:

Thanks for your response.

💫Remember that the render() has to be a pure function and it runs before componentDidMount().

Loading States With Redux

Summary

In this section, we looked at how to work with an external API. We added a new action (RECEIVE_DATA), created a new action creator, and built a new reducer…all to handle the different states our app can be in while getting our remote data:

  • before the app has the data
  • while the app is fetching the data
  • after the data has been received

In the next section, we'll look at how to optimistically update the UI based on the API actions that are performed.